/*
 * Copyright (c) 2019, AEye
 * All rights reserved.
 */

#include "AEyeSDKEnumsToStr.hpp"
#include "AEyeSDKToStrDev.h"
#include "ecast.h"
#include <sstream>
#include <iostream>

namespace aeye {

namespace detail {
template<typename E>
inline std::string ToStr(E e) {
  std::stringstream ss;
  ss << e;
  return ss.str();
}
}

std::string ToStr(PointReturnFlags v) {
  return detail::ToStr(v);
}
std::string ToStr(PassiveModeParam v) {
  return detail::ToStr(v);
}
std::string ToStr(PointFlags v) {
  return detail::ToStr(v);
}
std::string ToStr(ModelType v) {
  return detail::ToStr(v);
}
std::string ToStr(MultiEchoMode v) {
  return detail::ToStr(v);
}
std::string ToStr(ReturnStatus v) {
  return detail::ToStr(v);
}
std::string ToStr(PassiveModeFlags v) {
  return detail::ToStr(v);
}
std::string ToStr(AEyeCommands v) {
  return detail::ToStr(v);
}


#ifdef __GNUG__
#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-Wswitch-enum"
#endif

// this actually can't be a do-while macro, but it's not really a function-like macro, so it's fine
// additionally removes all chance of making a typo between the enum variant and string
#define ENUM_CASE(ENUM, VARIANT) case ENUM::VARIANT: os << #VARIANT; break

std::ostream &operator<<(std::ostream &os, PointReturnFlags v) {
  switch (v) {
    ENUM_CASE(PointReturnFlags, UNUSED_0);
    ENUM_CASE(PointReturnFlags, SPHERICAL_COORDINATES);
    ENUM_CASE(PointReturnFlags, UNUSED_1);
    ENUM_CASE(PointReturnFlags, INTENSITY);
    ENUM_CASE(PointReturnFlags, UNUSED_2);
    ENUM_CASE(PointReturnFlags, UNUSED_3);
    ENUM_CASE(PointReturnFlags, UNUSED_4);
    ENUM_CASE(PointReturnFlags, UNUSED_5);
    ENUM_CASE(PointReturnFlags, UNUSED_6);
    ENUM_CASE(PointReturnFlags, UNUSED_7);
    ENUM_CASE(PointReturnFlags, UNUSED_8);
  }
  return os;
}
std::ostream &operator<<(std::ostream &os, PassiveModeParam v) {
  switch (v) {
    ENUM_CASE(PassiveModeParam, GRID_ROW_NUM);
    ENUM_CASE(PassiveModeParam, GRID_COL_NUM);
    ENUM_CASE(PassiveModeParam, RANDOM_ROW_NUM);
    ENUM_CASE(PassiveModeParam, RANDOM_COL_NUM);
    ENUM_CASE(PassiveModeParam, OFFSET_GRID_ROW_NUM);
    ENUM_CASE(PassiveModeParam, OFFSET_GRID_COL_NUM);
    ENUM_CASE(PassiveModeParam, GRID_COLUMN_OFFSET);
    ENUM_CASE(PassiveModeParam, MOVING_GRID_ROW_NUM);
    ENUM_CASE(PassiveModeParam, MOVING_GRID_COL_NUM);
    ENUM_CASE(PassiveModeParam, GRID_COL_SPEED);
    ENUM_CASE(PassiveModeParam, GRID_ROW_SPEED);
    ENUM_CASE(PassiveModeParam, FOVEATED_GRID_ROW_NUM);
    ENUM_CASE(PassiveModeParam, FOVEATED_GRID_COL_NUM);
    ENUM_CASE(PassiveModeParam, GRID_FOVEATION_COEFFICIENT_COL);
    ENUM_CASE(PassiveModeParam, GRID_FOVEATION_COEFFICIENT_ROW);
    ENUM_CASE(PassiveModeParam, FOVEATED_GRID_CENTER_COL);
    ENUM_CASE(PassiveModeParam, FOVEATED_GRID_CENTER_ROW);
    ENUM_CASE(PassiveModeParam, FOVEATED_RANDOM_ROW_NUM);
    ENUM_CASE(PassiveModeParam, FOVEATED_RANDOM_COL_NUM);
    ENUM_CASE(PassiveModeParam, RANDOM_FOVEATION_COEFFICIENT_COL);
    ENUM_CASE(PassiveModeParam, RANDOM_FOVEATION_COEFFICIENT_ROW);
    ENUM_CASE(PassiveModeParam, FOVEATED_RANDOM_CENTER_COL);
    ENUM_CASE(PassiveModeParam, FOVEATED_RANDOM_CENTER_ROW);
    ENUM_CASE(PassiveModeParam, SHOTLIST_FILE_NUMBER);
  }
  return os;
}
std::ostream &operator<<(std::ostream &os, PointFlags v) {
  switch (v) {
    ENUM_CASE(PointFlags, ECHO_LSB);
    ENUM_CASE(PointFlags, ECHO_MSB);
    ENUM_CASE(PointFlags, RESERVED1);
    ENUM_CASE(PointFlags, RESERVED2);
    ENUM_CASE(PointFlags, RESERVED3);
    ENUM_CASE(PointFlags, RESERVED4);
    ENUM_CASE(PointFlags, RESERVED5);
    ENUM_CASE(PointFlags, RESERVED6);
    ENUM_CASE(PointFlags, RESERVED7);
    ENUM_CASE(PointFlags, RESERVED8);
    ENUM_CASE(PointFlags, RESERVED9);
    ENUM_CASE(PointFlags, RESERVED10);
    ENUM_CASE(PointFlags, RESERVED11);
    ENUM_CASE(PointFlags, RESERVED12);
    ENUM_CASE(PointFlags, RESERVED13);
    ENUM_CASE(PointFlags, RESERVED14);
    ENUM_CASE(PointFlags, RESERVED15);
    ENUM_CASE(PointFlags, RESERVED16);
    ENUM_CASE(PointFlags, RESERVED17);
    ENUM_CASE(PointFlags, RESERVED18);
    ENUM_CASE(PointFlags, RESERVED19);
    ENUM_CASE(PointFlags, RESERVED20);
    ENUM_CASE(PointFlags, RESERVED21);
    ENUM_CASE(PointFlags, RESERVED22);
    ENUM_CASE(PointFlags, RESERVED23);
    ENUM_CASE(PointFlags, RESERVED24);
    ENUM_CASE(PointFlags, RESERVED25);
    ENUM_CASE(PointFlags, RESERVED26);
    ENUM_CASE(PointFlags, RESERVED27);
    ENUM_CASE(PointFlags, RESERVED28);
    ENUM_CASE(PointFlags, RESERVED29);
    ENUM_CASE(PointFlags, RESERVED30);
  }
  return os;
}
std::ostream &operator<<(std::ostream &os, ModelType v) {
  switch (v) {
    ENUM_CASE(ModelType, UNKNOWN);
    ENUM_CASE(ModelType, FSM60A);
    ENUM_CASE(ModelType, FSM60B);
    ENUM_CASE(ModelType, FSM120);
    ENUM_CASE(ModelType, RESERVED_1);
    ENUM_CASE(ModelType, RESERVED_2);
    ENUM_CASE(ModelType, APOLLO_A1);
    ENUM_CASE(ModelType, APOLLO_A2);
    ENUM_CASE(ModelType, APOLLO_B0);
    ENUM_CASE(ModelType, VIRTUAL);
  }
  return os;
}
std::ostream &operator<<(std::ostream &os, MultiEchoMode v) {
  switch (v) {
    ENUM_CASE(MultiEchoMode, FIRST);
    ENUM_CASE(MultiEchoMode, STRONGEST);
  }
  return os;
}
std::ostream &operator<<(std::ostream &os, ReturnStatus v) {
  switch (v) {
    ENUM_CASE(ReturnStatus, NO_ERRORS);
    ENUM_CASE(ReturnStatus, GENERIC_ERROR);
    ENUM_CASE(ReturnStatus, ALREADY_RUNNING);
    ENUM_CASE(ReturnStatus, NOT_RUNNING);
    ENUM_CASE(ReturnStatus, COULD_NOT_CREATE_THREAD);
    ENUM_CASE(ReturnStatus, ZERO_POINTS);
    ENUM_CASE(ReturnStatus, BAD_SHOTLIST);
    ENUM_CASE(ReturnStatus, NETWORK_ERROR);
    ENUM_CASE(ReturnStatus, UNKNOWN_COMMAND);
    ENUM_CASE(ReturnStatus, INCORRECT_PACKET_SIZE);
    ENUM_CASE(ReturnStatus, BAD_PARAMETER);
    ENUM_CASE(ReturnStatus, EYESAFETY_SHUTDOWN_OCCURRED);
    ENUM_CASE(ReturnStatus, UNSUPPORTED_VERSION);
    ENUM_CASE(ReturnStatus, AUTOMATIC_STATE_CHANGE);
    ENUM_CASE(ReturnStatus, DISALLOWED_COMMAND);
    ENUM_CASE(ReturnStatus, NOT_IMPLEMENTED_YET);
    ENUM_CASE(ReturnStatus, BAD_FILE);
    ENUM_CASE(ReturnStatus, LASER_ERROR);
    ENUM_CASE(ReturnStatus, CONFIG_ERROR);
    default:
      os << std::to_string(ut_cast(v));
      break;
  }
  return os;
}
std::ostream &operator<<(std::ostream &os, PassiveModeFlags v) {
  switch (v) {
    ENUM_CASE(PassiveModeFlags, DISABLED);
    ENUM_CASE(PassiveModeFlags, GRID);
    ENUM_CASE(PassiveModeFlags, RANDOM);
    ENUM_CASE(PassiveModeFlags, OFFSET_GRID);
    ENUM_CASE(PassiveModeFlags, FOVEATED_GRID);
    ENUM_CASE(PassiveModeFlags, FOVEATED_RANDOM);
    ENUM_CASE(PassiveModeFlags, MOVING_GRID);
    ENUM_CASE(PassiveModeFlags, SHOTLIST_FROM_FILE);
  }
  return os;
}
std::ostream &operator<<(std::ostream &os, AEyeCommands v) {
  switch (v) {
    ENUM_CASE(AEyeCommands, CMD_GET_BUILD_INFO);
    ENUM_CASE(AEyeCommands, CMD_GET_HW_MODEL);
    ENUM_CASE(AEyeCommands, CMD_SET_NETWORK_CONFIG);
    ENUM_CASE(AEyeCommands, CMD_SET_TIME);
    ENUM_CASE(AEyeCommands, CMD_SET_NTP_SERVER);
    ENUM_CASE(AEyeCommands, CMD_GET_NTP_STATUS);
    ENUM_CASE(AEyeCommands, CMD_SET_PTP_SERVER);
    ENUM_CASE(AEyeCommands, CMD_GET_PTP_STATUS);
    ENUM_CASE(AEyeCommands, CMD_SET_GPTP_SERVER);
    ENUM_CASE(AEyeCommands, CMD_GET_GPTP_STATUS);
    ENUM_CASE(AEyeCommands, CMD_SET_RANGE_GATE_DELAY);
    ENUM_CASE(AEyeCommands, CMD_SET_POSE);
    ENUM_CASE(AEyeCommands, CMD_SET_ERPS_BOX_IN_CAM_COORDS);
    ENUM_CASE(AEyeCommands, CMD_START);
    ENUM_CASE(AEyeCommands, CMD_STOP);
    ENUM_CASE(AEyeCommands, CMD_TOGGLE_HAWKEYE);
    ENUM_CASE(AEyeCommands, CMD_SET_PASSIVE_SENSING_MODE);
    ENUM_CASE(AEyeCommands, CMD_SET_HAWKEYE_POINT_MODE);
    ENUM_CASE(AEyeCommands, CMD_RET_MARKER_POINTS);
    ENUM_CASE(AEyeCommands, CMD_SET_ADVANCED_RX_SWEEP);
    ENUM_CASE(AEyeCommands, CMD_SET_ADVANCED_RX_STATIC_MODE);
    ENUM_CASE(AEyeCommands, CMD_SET_MODE_MULTI_ECHOES);
    ENUM_CASE(AEyeCommands, CMD_SET_POINT_RETURN_MASK);
    ENUM_CASE(AEyeCommands, CMD_SET_RECEIVER_REGISTER);
    ENUM_CASE(AEyeCommands, CMD_GET_RECEIVER_REGISTER);
    ENUM_CASE(AEyeCommands, CMD_SET_PASSIVE_MODE_PARAMETER);
    ENUM_CASE(AEyeCommands, CMD_GET_POSE);
    ENUM_CASE(AEyeCommands, CMD_GET_ACTIVE_SENSING_STATE);
    ENUM_CASE(AEyeCommands, CMD_GET_PASSIVE_SENSING_STATE);
    ENUM_CASE(AEyeCommands, CMD_GET_ERPS_SENSING_STATE);
    ENUM_CASE(AEyeCommands, CMD_GET_RANGING_STATE);
    ENUM_CASE(AEyeCommands, CMD_GET_LASER_STATE);
    ENUM_CASE(AEyeCommands, CMD_GET_MARKER_STATE);
    ENUM_CASE(AEyeCommands, RET_POINT_CLOUD);
    ENUM_CASE(AEyeCommands, RET_ADC_BUFFER);
    ENUM_CASE(AEyeCommands, RET_POINT_CLOUD_DELIM);
    ENUM_CASE(AEyeCommands, RET_DEFAULT);
    ENUM_CASE(AEyeCommands, RET_UNKNOWN);
    ENUM_CASE(AEyeCommands, RET_BUILD_INFO);
    ENUM_CASE(AEyeCommands, RET_HW_MODEL);
    ENUM_CASE(AEyeCommands, RET_GET_NUM_MULTI_ECHOES);
    ENUM_CASE(AEyeCommands, RET_GET_MODE_MULTI_ECHOES);
    ENUM_CASE(AEyeCommands, RET_SCANNER_REGISTER_VALUE);
    ENUM_CASE(AEyeCommands, RET_RECEIVER_REGISTER_VALUE);
    ENUM_CASE(AEyeCommands, RET_POSE_VALUE);
    ENUM_CASE(AEyeCommands, RET_ACTIVE_SENSING_STATE);
    ENUM_CASE(AEyeCommands, RET_PASSIVE_SENSING_STATE);
    ENUM_CASE(AEyeCommands, RET_ERPS_SENSING_STATE);
    ENUM_CASE(AEyeCommands, RET_RANGING_STATE);
    ENUM_CASE(AEyeCommands, RET_LASER_STATE);
    ENUM_CASE(AEyeCommands, RET_MARKER_STATE);
    ENUM_CASE(AEyeCommands, RET_RECEIVER_REGISTERS_VALUE);
    ENUM_CASE(AEyeCommands, CMD_WRITE_SCANNER_REGISTER);
    ENUM_CASE(AEyeCommands, CMD_READ_SCANNER_REGISTER);
    ENUM_CASE(AEyeCommands, CMD_WRITE_HAWKEYE_REGISTERS);
    ENUM_CASE(AEyeCommands, RET_READ_HAWKEYE_REGISTERS);
    ENUM_CASE(AEyeCommands, CMD_SET_NUM_MULTI_ECHOES);
    ENUM_CASE(AEyeCommands, CMD_GET_NUM_MULTI_ECHOES);
    ENUM_CASE(AEyeCommands, CMD_GET_MODE_MULTI_ECHOES);
    ENUM_CASE(AEyeCommands, CMD_REBOOT);
    ENUM_CASE(AEyeCommands, CMD_SET_SKIRT_THRESH_NEAR_HIGH);
    ENUM_CASE(AEyeCommands, CMD_SET_SKIRT_THRESH_NEAR_LOW);
    ENUM_CASE(AEyeCommands, CMD_SET_SKIRT_THRESH_FAR_HIGH);
    ENUM_CASE(AEyeCommands, CMD_SET_SKIRT_THRESH_FAR_LOW);
    ENUM_CASE(AEyeCommands, CMD_GET_SKIRT_THRESH_NEAR_HIGH);
    ENUM_CASE(AEyeCommands, CMD_GET_SKIRT_THRESH_NEAR_LOW);
    ENUM_CASE(AEyeCommands, CMD_GET_SKIRT_THRESH_FAR_HIGH);
    ENUM_CASE(AEyeCommands, CMD_GET_SKIRT_THRESH_FAR_LOW);
    ENUM_CASE(AEyeCommands, CMD_GET_SHOTLIST_NAME);
    ENUM_CASE(AEyeCommands, RET_SHOTLIST_NAME);
    ENUM_CASE(AEyeCommands, RET_DIAG_DATA);
    ENUM_CASE(AEyeCommands, CMD_GET_HAWKEYE_BUFFER);
    ENUM_CASE(AEyeCommands, CMD_SET_ARX_PIXEL);
    ENUM_CASE(AEyeCommands, CMD_HAWKEYE_SCANNING_MODE);
    ENUM_CASE(AEyeCommands, CMD_SET_LASER_ENABLE);
    ENUM_CASE(AEyeCommands, CMD_KILL_SERVICE);
    ENUM_CASE(AEyeCommands, CMD_GENERATE_ARX_LUT_V2);
    ENUM_CASE(AEyeCommands, CMD_GET_NETWORK_CONFIG);
    ENUM_CASE(AEyeCommands, CMD_SEND_ZONE_SCAN_PARAMS);
    ENUM_CASE(AEyeCommands, CMD_GET_BUILD_INFO_EXTRA);
    ENUM_CASE(AEyeCommands, CMD_SET_RX_FOV);
    ENUM_CASE(AEyeCommands, CMD_SET_LASER_CONFIG_FLOAT);
    ENUM_CASE(AEyeCommands, CMD_GET_GENERATE_ARX_LUT_V2_STATUS);
    ENUM_CASE(AEyeCommands, CMD_SET_HFOV);
    ENUM_CASE(AEyeCommands, CMD_GET_HSYNC_PARAMETERS);
  }
  return os;
}

std::ostream &operator<<(std::ostream &os, TimeServerStatus v) {
  switch (v) {
    ENUM_CASE(TimeServerStatus, SYNCHRONIZED);
    ENUM_CASE(TimeServerStatus, DESYNCHRONIZED);
    ENUM_CASE(TimeServerStatus, INDETERMINATE);
    ENUM_CASE(TimeServerStatus, OFF);
  }
  return os;
}

#ifdef __GNUG__
#pragma GCC diagnostic pop // -Wswitch-enum
#endif

}
